package retrievedatafromrevishapi;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.LinkedList;

import xmlextract.GetTagContent;

import bookworm.Review;

/**
 * This class will not use revish api to get Reviews from books. Instead, it'll use text files.
 * the text files are named after the tags used by our system, so when a name for the text
 * file is needed, we'll use the arguments values(this is because we know that our system
 * will only call the functions defined by the "InterfaceGetBookReviewData" when it's related
 * to search for book reviews from a specific tag on Revish)
 * @author Mina
 *
 */
public class GetReviewDataFromTextFile implements InterfaceGetBookReviewData
{
	public LinkedList<Review> getAllBookReviewsFromRevishAPI(LinkedList<String> searchArguments, LinkedList<String> argumentsValue)
	{
		String textFileName = argumentsValue.get(0) + ".txt";
		String XMLWithReviewsFromBook = 
				getXMLWithReviewsFromRevishAPI(searchArguments, argumentsValue, textFileName);
		GetTagContent getsTagContentFromXML = new GetTagContent();
		String totalReviews = getsTagContentFromXML.getTagContent(XMLWithReviewsFromBook, "totalreviews");
		//now we have he total of reviews from our tag. let's add as an argument of our search
		//the limit of reviews. By default, it's 20. But we don't want 20...
		searchArguments.add("limit");
		argumentsValue.add(totalReviews);
		return this.getBookReviewsFromRevishAPI(searchArguments, argumentsValue);
		
	}
	
	public int getNumberOfBookReviewsFromRevishAPI(LinkedList<String> searchArguments, LinkedList<String> argumentsValue)
	{
		String textFileName = argumentsValue.get(0) + ".txt";
		String XMLWithReviewsFromBook = 
				getXMLWithReviewsFromRevishAPI(searchArguments, argumentsValue, textFileName);
		GetTagContent getsTagContentFromXML = new GetTagContent();
		String totalReviews = getsTagContentFromXML.getTagContent(XMLWithReviewsFromBook, "totalreviews");
		
		return Integer.valueOf(totalReviews);
	}
	
	public LinkedList<Review> getBookReviewsFromRevishAPI(LinkedList<String> searchArguments, LinkedList<String> argumentsValue)
	{
		/* note: the parameters in this method are arguments to add in the search for book reviews */
		
		String textFileName = argumentsValue.get(0) + ".txt";
		String XMLWithReviewsFromBook = 
				getXMLWithReviewsFromRevishAPI(searchArguments, argumentsValue, textFileName);
		LinkedList<String> separateXMLFromEachReview = getXMLFromEachReview(XMLWithReviewsFromBook);
		LinkedList<Review> bookReviews = getReviewsFromXMLFromEachReview(separateXMLFromEachReview);
		return bookReviews;
	}
	
	private String getXMLWithReviewsFromRevishAPI(LinkedList<String> searchArguments, LinkedList<String> argumentsValue, String TextFileName)
	{
		try
		{
			FileInputStream inputStream = new FileInputStream(TextFileName);
			Reader reader = new InputStreamReader(inputStream, "UTF-8");
			BufferedReader bufferedReader = new BufferedReader(reader);
			String readLine = bufferedReader.readLine();
			String XMLWithReviews = "";
			while(readLine != null)
			{
				XMLWithReviews = XMLWithReviews + readLine;
				readLine = bufferedReader.readLine();
			}
			
			return XMLWithReviews;
		}
		catch(IOException exc)
		{
			System.out.println(exc);
			return getXMLWithReviewsFromRevishAPI(searchArguments, argumentsValue, TextFileName);
		}
	}
	
	
	
	private LinkedList<String> getXMLFromEachReview(String XMLWithReviewsFromBook)
	{
		GetTagContent getContent = new GetTagContent();
		LinkedList<String> XMLFromEachReview = 
				getContent.getTagContentsMultipleOccurrences(XMLWithReviewsFromBook, "review");
		return XMLFromEachReview;
	}
	
	
	private Review getReviewFromXML(String XMLOfOneReview)
	{
		Review review = new Review();
		GetTagContent getContent = new GetTagContent();
		
		String idInString = getContent.getTagContent(XMLOfOneReview, "reviewid");
		int reviewId = Integer.valueOf(idInString);
		
		String isbnInString = getContent.getTagContent(XMLOfOneReview, "isbn");
		String isbn = isbnInString;
		
		String bookTitle = getContent.getTagContent(XMLOfOneReview, "booktitle");
		LinkedList<String> authors = getContent.getTagContentsMultipleOccurrences(XMLOfOneReview, "author");
		String reviewer = getContent.getTagContent(XMLOfOneReview, "reviewer");
		String reviewTitle = getContent.getTagContent(XMLOfOneReview, "reviewtitle");
		String publisher = getContent.getTagContent(XMLOfOneReview, "publisher");
		String reviewDate = getContent.getTagContent(XMLOfOneReview, "reviewdate");
		String ratingInString = getContent.getTagContent(XMLOfOneReview, "rating");
		int rating = Integer.valueOf(ratingInString);
		String urlReview = getContent.getTagContent(XMLOfOneReview, "url");
		String smallCover = getContent.getTagContent(XMLOfOneReview, "smallcover");
		String mediumCover = getContent.getTagContent(XMLOfOneReview, "mediumcover");
		LinkedList<String> linksWhereToBuyBook = new LinkedList<String>();
		String linkAmazon = getContent.getTagContentWithType(XMLOfOneReview, "link", "amazon.com");
		String linkAmazonUk = getContent.getTagContentWithType(XMLOfOneReview, "link", "amazon.co.uk");
		String linkAmazonCa = getContent.getTagContentWithType(XMLOfOneReview, "link", "amazon.ca");
		String linkLibraryThing = getContent.getTagContentWithType(XMLOfOneReview, "link", "librarything");
		
		if(linkAmazon.compareTo("") != 0)
		{
			linksWhereToBuyBook.add(linkAmazon);
		}
		if(linkAmazonUk.compareTo("") != 0)
		{
			linksWhereToBuyBook.add(linkAmazonUk);
		}
		if(linkAmazonCa.compareTo("") != 0)
		{
			linksWhereToBuyBook.add(linkAmazonCa);
		}
		if(linkLibraryThing.compareTo("") != 0)
		{
			linksWhereToBuyBook.add(linkLibraryThing);
		}
		
		String reviewText = getContent.getTagContent(XMLOfOneReview, "reviewtext");
		reviewText = reviewText.replace("<![CDATA[", "").replace("]]>", "");
		
		
		String allTagsUnited = getContent.getTagContent(XMLOfOneReview, "tags");
		/*the Revish api gives us the tags related to the book review, but they are separated by 
		  a blank space. And they are all united in the same String. Let's get these tags*/
		LinkedList<String> tags = getTagsFromAllTagsUnited(allTagsUnited);
		
		review.setAuthors(authors);
		review.setBookTitle(bookTitle);
		
		review.setReviewId(reviewId);
		review.setIsbn(isbn);
		review.setLinksWhereToBuyBook(linksWhereToBuyBook);
		review.setMediumCover(mediumCover);
		review.setPublisher(publisher);
		review.setRating(rating);
		review.setReviewDate(reviewDate);
		review.setReviewer(reviewer);
		review.setReviewText(reviewText);
		review.setReviewTitle(reviewTitle);
		review.setSmallCover(smallCover);
		review.setUrlReview(urlReview);
		review.setTags(tags);
		
		return review;
	}
	
	private LinkedList<Review> getReviewsFromXMLFromEachReview(LinkedList<String> separateXMLFromEachReview)
	{
		LinkedList<Review> reviews = new LinkedList<Review>();
		for(int i = 0; i < separateXMLFromEachReview.size(); i++)
		{
			String XMLFromOneReview = separateXMLFromEachReview.get(i);
			Review newReview = getReviewFromXML(XMLFromOneReview);
			reviews.add(newReview);
		}
		return reviews;
	}
	
	private LinkedList<String> getTagsFromAllTagsUnited(String allTagsUnited)
	{
		LinkedList<String> separatedTags = new LinkedList<String>();
		String oneTag = "";
		for(int i = 0; i < allTagsUnited.length(); i++)
		{
			char oneChar = allTagsUnited.charAt(i);
			String oneCharInString = String.valueOf(oneChar);
			if(oneCharInString.compareTo(" ") == 0)
			{
				if(oneTag.startsWith("\"") == false || (oneTag.startsWith("\"") == true && oneTag.endsWith("\"") == true) )
				{
					//if one tag starts with ", then it's a compund tag and will only finish with the ending ".
					if((oneTag.startsWith("\"") == true && oneTag.endsWith("\"") == true))
					{
						oneTag = oneTag.substring(1, oneTag.length() - 1);//without " ".
					}
					separatedTags.add(oneTag.toLowerCase());
					oneTag = "";
				}
				
			}
			else
			{
				oneTag = oneTag + oneCharInString;
			}
		}
		
		//there's just one tag that didn't have the space at the end of it.
		if(oneTag.startsWith("\"") && oneTag.endsWith("\""))
		{
			//it's a compound tag, then the " must be removed before adding it
			oneTag = oneTag.substring(1, oneTag.length() - 1);//without " ".
			
		}
		separatedTags.add(oneTag.toLowerCase());
		
		return separatedTags;
	}

}
